package com.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.util.FileCopyUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/** 
 * Downloads RFCs 
 *  
 * @author lying~
 *  
 */
@Slf4j
public class DownloadFileUtils {
  
    /** 
     * @param args 
     */  
    public static void main(String[] args) {
        String source = "https://services.frayun.com/TempDown/PDF/FS-YKSZ-09900595914677.pdf";
        String des = "FS-YKSZ-09900595914677.pdf";
        System.out.println("开始下载，请耐心等待");
            downloadAndSave(source, des);
        System.out.println("恭喜你，全部下载成功！");
          
  
    }  
  
    /** 
     * 从网页中读取文件名列表 
     *  
     * @param urlString 
     * @return 
     */  
    public static String[] readList(String urlString) {  
  
        String[] lists = new String[6734];  
        try {  
            URL url = new URL(urlString);  
            Scanner scanner = new Scanner(url.openStream());  
            int i = 0;  
            int up = 6960; // 226  
            while (scanner.hasNextLine() && i < up) {  
                String line = scanner.nextLine();  
                if (i >= 226) {  
                    lists[i - 226] = dealString(line);  
                }  
                i++;  
            }  
            scanner.close();  
        } catch (MalformedURLException e) {
            log.error("URL格式出错，请检查");
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }
        return lists;  
  
    }  
  
    /** 
     * 从网页的<li>元素中提取文件名 
     *  
     * @param source 
     *            待处理的<li>元素 
     * @return 处理后的文件名 
     */  
    public static String dealString(String source) {  
        String string = source;  
        String result = string;  
        String patterString = ">\\s.+.pdf";  
        Pattern pattern = Pattern.compile(patterString);  
        Matcher macher = pattern.matcher(string);  
        while (macher.find()) {  
            int start = macher.start();  
            int end = macher.end();  
            result = string.substring(start, end);  
        }  
        result = result.substring(2, result.length());  
        return result;  
    }  
  
    /** 
     * @param source 
     *            the url of PDF to be downloaded 
     * @param destination 
     *            the destination to be saved 
     */  
    public static void downloadAndSave(String source, String destination) {  
        try {  
            URL url = new URL(source); // "http://ietfreport.isoc.org/rfc/PDF/rfc1341.pdf");  
            File file = new File(destination); // "rfc1341.pdf");  
            FileUtils.copyURLToFile(url, file);  
            log.info(source + "下载完成");
        } catch (MalformedURLException e) {  
            log.error("URL格式出错，请检查");
            e.printStackTrace();  
        } catch (IOException e) {
            log.error("I/O 错误");
            e.printStackTrace();  
        }  
    }

    /**
     * 下载文件压缩包
     * req 请求头
     * response 返回体
     * fileInfoList 文件信息集合
     */
    public static void downForZip(HttpServletRequest req, HttpServletResponse response, List<File> fileList) throws Exception {
        // 创建临时文件
        File zipFile = null;
        FileInputStream fis = null;
        BufferedInputStream buff = null;
        try {
            //临时文件名称
            zipFile = File.createTempFile(System.currentTimeMillis()+"asmx", ".zip");
            FileOutputStream fot = new FileOutputStream(zipFile);
            // 为任何OutputStream产生校验，第一个参数是制定产生校验和的输出流，第二个参数是指定Checksum的类型 (Adler32(较快)和CRC32两种)
            CheckedOutputStream cos = new CheckedOutputStream(fot, new Adler32());
            // 用于将数据压缩成Zip文件格式
            ZipOutputStream zos = new ZipOutputStream(cos);
            for (File file: fileList) {
                //根据文件信息获取输入流。这个看实际的业务目的就是获取当前文件的输入流
                InputStream inputStream = new FileInputStream(file);
                if (!file.exists()) {
                   continue;
                }
                // 对于每一个要被存放到压缩包的文件，都必须调用ZipOutputStream对象的putNextEntry()方法，确保压缩包里面文件不同名
                //多个文件名称重复时zos.putNextEntry()会报错！！ 可以再文件名称后面加编号等操作
                zos.putNextEntry(new ZipEntry(file.getName()));
                int bytesRead = 0;
                // 向压缩文件中输出数据
                while ((bytesRead = inputStream.read()) != -1) {
                    zos.write(bytesRead);
                }
                inputStream.close();
                // 当前文件写完，写入下一个文件
                zos.closeEntry();
            }
            zos.close();
            //下载文件,使用spring框架中的FileCopyUtils工具
            response.setCharacterEncoding("GB2312");
            response.setContentType(req.getSession().getServletContext().getMimeType(zipFile.getName()));
            //设置响应头,attachment表示以附件的形式下载，inline表示在线打开
            response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode(zipFile.getName(), "UTF-8"));
            fis = new FileInputStream(zipFile);
            buff = new BufferedInputStream(fis);
            ServletOutputStream os = response.getOutputStream();
            FileCopyUtils.copy(buff, os);
        } catch (Exception e1) {
            throw new Exception("批量下载失败");
            // 关闭流
        } finally {
            try {
                if (null != fis) {
                    fis.close();
                }
                if (null != buff) {
                    buff.close();
                }
            } catch (IOException e) {
                log.error( "流关闭异常");
            }
            // 删除临时文件
            if (null != zipFile) {
                zipFile.delete();
            }
        }
    }


}  